package it.orma.iridehr.repository;

import it.orma.iridehr.controllers.ricerca.RicercaForm;
import it.orma.iridehr.entities.*;
import it.orma.iridehr.services.helper.RisultatoRicerca;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public class RicercaRepository {

	@PersistenceContext
	private EntityManager entityManager;

	public List<RisultatoRicerca> ricercaCandidati(RicercaForm ricercaForm){
		ricercaForm.setTipoRicerca("cercacandidati");
		
		StringTokenizer tokenizerNome = new StringTokenizer(ricercaForm.getNome().toUpperCase().replaceAll(" +"," "));
		StringTokenizer tokenizerCognome = new StringTokenizer(ricercaForm.getCognome().toUpperCase().replaceAll(" +"," "));
		String criteria = ricercaForm.getCriteria();
		StringBuilder whereClauseCognome = new StringBuilder("(");
		StringBuilder whereClauseNome = new StringBuilder("(");
		while (tokenizerCognome.hasMoreTokens()){
			String token = tokenizerCognome.nextToken();
			whereClauseCognome.append(" upper(d.cognome) like '%"+token.toUpperCase().replaceAll("'","''")+"%' "+ criteria);
		}
		while (tokenizerNome.hasMoreTokens()){
			String token = tokenizerNome.nextToken();
			whereClauseNome.append(" upper(d.nome) like '%"+token.toUpperCase().replaceAll("'","''")+"%' "+ criteria);
		}
		
		String queryHql = "select count(d) "
		+ " from "+ DatiGenerali.class.getCanonicalName() + " as d inner join d.schedaCandidato s "
		+" where 1=1 ";
		if (whereClauseCognome.length()>1)
			queryHql+=" and "+whereClauseCognome.toString().substring(0,whereClauseCognome.toString().lastIndexOf(criteria)).concat(")");
		if (whereClauseNome.length()>1)
			queryHql+=" and "+whereClauseNome.toString().substring(0,whereClauseNome.toString().lastIndexOf(criteria)).concat(")");
//		+ " where upper(d.cognome) like '%"+ricercaForm.getQuery().toUpperCase() + "%' or "
//		+ " upper(d.nome) like '%"+ricercaForm.getQuery().toUpperCase() + "%'";
		Query query = entityManager.createQuery(queryHql);
		ricercaForm.setResultSize(new Long((Long) query.getSingleResult()).intValue());
		
		queryHql = "select s.idSchedaCandidato,s.idDocumentoCurriculum, d.cognome, d.nome, d.dataDiNascita, d.comuneDiNascita, d.provinciaDiNascita, s.dataModifica "
				+ " from "+ DatiGenerali.class.getCanonicalName() + " as d inner join d.schedaCandidato s "
//				+ " where upper(d.cognome) like :query or "
//				+ " upper(d.nome) like :query";
				+" where 1=1 ";
				if (whereClauseCognome.length()>1)
					queryHql+=" and "+whereClauseCognome.toString().substring(0,whereClauseCognome.toString().lastIndexOf(criteria)).concat(")");
				if (whereClauseNome.length()>1)
					queryHql+=" and "+whereClauseNome.toString().substring(0,whereClauseNome.toString().lastIndexOf(criteria)).concat(")");
//		session. .setMaxResults(ricercaForm.getRecordPerPagina());
//		getHibernateTemplate().setFetchSize(ricercaForm.getPagina());
		query = entityManager.createQuery(queryHql);
//		query.setParameter("query", "%"+ricercaForm.getQuery().toUpperCase()+"%");

		query.setFirstResult(ricercaForm.getPagina());
		query.setMaxResults(ricercaForm.getRecordPerPagina());
		List risultati = query.getResultList();

		return convertiLista(risultati);
	}
	
	public Long ricercaCandidato(String nickName){
		String queryHql = "select s.idSchedaCandidato "+
				 " from "+SchedaCandidato.class.getCanonicalName()+" s, "+Users.class.getCanonicalName()+" u "+
		         " where u.userName ='"+nickName+"'"+
		         " and  s.idSchedaCandidato = u.userId"; 
		Query query = entityManager.createQuery(queryHql);
		query = entityManager.createQuery(queryHql);

		List risultati = query.getResultList();
		Iterator iterator = risultati.iterator();
		Object record = (Object) iterator.next();
		return (Long)record;
	}
	
	public List<Object> ricercaLinkAlfrescoDB(String email){
		String nativeSql = "select dg.fk_scheda_candidato from dati_generali dg where dg.ds_mail1 = ? "; 
		Query query = entityManager.createNativeQuery(nativeSql);
		query.setParameter(1, email);

		List<Object> risultati = (List<Object>) query.getResultList();
		return risultati;
	}
	
	public List<CVCandidato> ricercaDocumenti(Long idCandidato, String tipo){
		String queryHql = "select s "+
				 " from "+CVCandidato.class.getCanonicalName()+" s"+
		         " where s.idCandidato = ?"+
		         " and  s.tipo = ?"; 
		Query query = entityManager.createQuery(queryHql);
		query.setParameter(1, idCandidato);
		query.setParameter(2, tipo);
		
		List<CVCandidato> risultati =  query.getResultList();
		entityManager.detach(risultati);
		return risultati;
		
	}

	private List<RisultatoRicerca> convertiLista(List risultati) {
		List<RisultatoRicerca> risultatiRicerca = new ArrayList<RisultatoRicerca>();
		for (Iterator iterator = risultati.iterator(); iterator
				.hasNext();) {
			Object[] record = (Object[]) iterator.next();
			StringBuilder dettaglio = new StringBuilder((String) record[3]).append(" ").append(record[2]);
			dettaglio.append(" nato/a il ").append(DateFormatUtils.format((Date)record[4],"dd/MM/yyyy")).append(" a ").append(record[5]).append(" (").append(record[6])
			.append(")");
			RisultatoRicerca rr = new RisultatoRicerca((Long)record[0], (String)record[1], dettaglio.toString(), (Date)record[7]);
			risultatiRicerca.add(rr);
		}
		return risultatiRicerca;
	}

	public SchedaCandidato caricaSchedaCandidato(Long idSchedaCandidato){
		String hql = "select s from "+SchedaCandidato.class.getName()+" as s where s.idSchedaCandidato = ?";
		SchedaCandidato scheda = (SchedaCandidato) entityManager.createQuery(hql).setParameter(1, idSchedaCandidato).getSingleResult();
		return scheda;
	}
	
	public SchedaCandidato creaSchedaCandidato(){
		SchedaCandidato scheda = new SchedaCandidato();
		scheda.setDataCreazione(new Date());

		return scheda;
	}

	public DatiGenerali caricaDatiGenerali(SchedaCandidato schedaCandidato){
		String hql = "select d from "+DatiGenerali.class.getName()+" as d inner join fetch d.schedaCandidato as s where d.schedaCandidato = ?";
		List<DatiGenerali> list = (List<DatiGenerali>)entityManager.createQuery(hql).setParameter(1,schedaCandidato).getResultList();
		DatiGenerali dg = null;
		if (list.size()==1){
			dg = (DatiGenerali) list.get(0);
			entityManager.detach(dg);
		}
		return dg;
	}

	public StudiCompiuti caricaStudiCompiuti(SchedaCandidato schedaCandidato) {
		String hql ="select s from "+StudiCompiuti.class.getName()+" as s left join fetch s.titoliDiStudio as t inner join fetch s.schedaCandidato sc where s.schedaCandidato=?";
		StudiCompiuti sc = new StudiCompiuti();
		try{
			sc = (StudiCompiuti) entityManager.createQuery(hql).setParameter(1, schedaCandidato).getSingleResult();
		}catch (NoResultException ne){
			sc.setTitoliDiStudio(new HashSet<TitoloDiStudio>());
			sc.setSchedaCandidato(schedaCandidato);
			sc.setDataCreazione(new Date());
			entityManager.persist(sc);
		}
		return sc;
	}

	public TitoloDiStudio caricaTitoloDiStudio(Long idTitoloDiStudio){
		String hql = "select t from "+TitoloDiStudio.class.getName()+" as t inner join t.studiCompiuti as s where t.idTitoloDiStudio =?";
		TitoloDiStudio ts = (TitoloDiStudio) entityManager.createQuery(hql).setParameter(1, idTitoloDiStudio).getSingleResult();
		return ts;
	}

	public LingueConosciute caricaLingueConosciute(SchedaCandidato schedaCandidato) {
		String hql ="select l from "+LingueConosciute.class.getName()+" as l left join fetch l.altreLingue as a inner join fetch l.schedaCandidato sc where l.schedaCandidato=?";
		LingueConosciute lc = new LingueConosciute();
		try{
			lc = (LingueConosciute) entityManager.createQuery(hql).setParameter(1, schedaCandidato).getSingleResult();
		}catch(NoResultException ne){
			lc.setSchedaCandidato(schedaCandidato);
			lc.setDataCreazione(new Date());
			entityManager.persist(lc);

		}
		entityManager.detach(lc);
		return lc;
	}

	public AltraLingua caricaAltraLingua(Long idAltraLingua){
		String hql = "select a from "+AltraLingua.class.getName() +" as a where a.idAltraLingua=:idAltraLingua";
		AltraLingua a = (AltraLingua) entityManager.createQuery(hql).setParameter("idAltraLingua", idAltraLingua).getSingleResult();
		return a;
	}

	public ConoscenzeInformatiche caricaConoscenzaInformatica(SchedaCandidato schedaCandidato){
		String hql = "from "+ConoscenzeInformatiche.class.getName()+" as c left join fetch c.altreConoscenzeInformatiche  where c.schedaCandidato=?";
		ConoscenzeInformatiche conoscenzeInformatiche = new ConoscenzeInformatiche();
		try {
			conoscenzeInformatiche = (ConoscenzeInformatiche) entityManager.createQuery(hql).setParameter(1,schedaCandidato).getSingleResult();
		} catch (NoResultException ne){
			conoscenzeInformatiche.setSchedaCandidato(schedaCandidato);
			conoscenzeInformatiche.setDataCreazione(new Date());
			entityManager.persist(conoscenzeInformatiche);
		}

		entityManager.detach(conoscenzeInformatiche);
		return conoscenzeInformatiche;
	}

	public AltraConoscenzaInformatica caricaAltraConoscenzaInformatica(Long idAltraConoscenzaInformatica){
		AltraConoscenzaInformatica a = entityManager.find(AltraConoscenzaInformatica.class,idAltraConoscenzaInformatica);
		entityManager.detach(a);
		return a;
	}

	public List<EsperienzaLavorativa> caricaEsperienzeLavorative(SchedaCandidato schedaCandidato) {
		String hql = "from "+EsperienzaLavorativa.class.getName()+" as n where n.schedaCandidato=? order by n.dataDa desc";
		List<EsperienzaLavorativa> results = entityManager.createQuery(hql).setParameter(1,schedaCandidato).getResultList();
		entityManager.detach(results);
		return results;
	}

	public EsperienzaLavorativa caricaEsperienzaLavorativa(Long idEsperienzaLavorativa) {
		EsperienzaLavorativa esperienzaLavorativa = entityManager.find(EsperienzaLavorativa.class,idEsperienzaLavorativa);
		entityManager.detach(esperienzaLavorativa);
		return esperienzaLavorativa;
	}
	
	public List<Attitudine> caricaAttitudini(SchedaCandidato schedaCandidato) {
		String hql = "from "+Attitudine.class.getName()+" as n where n.idCandidato=? order by idDomanda asc";
		List<Attitudine> results = entityManager.createQuery(hql).setParameter(1,schedaCandidato.getIdSchedaCandidato()).getResultList();
		entityManager.detach(results);
		return results;
	}
	
	public List<DomandaAttitudinale> caricaDomandeRisposte() {
		String hql = "from "+DomandaAttitudinale.class.getName();
		List<DomandaAttitudinale> results = entityManager.createQuery(hql).getResultList();
		entityManager.detach(results);
		return results;
	}
	
	public AltreInformazioni caricaAltreInfo(SchedaCandidato schedaCandidato) {
		String hql = "select a from "+AltreInformazioni.class.getName() +" as a where a.schedaCandidato=?";
		AltreInformazioni ai = new AltreInformazioni();
		try{	
			 ai =(AltreInformazioni) entityManager.createQuery(hql).setParameter(1,schedaCandidato).getSingleResult();
		}catch(NoResultException ne){
			ai.setSchedaCandidato(schedaCandidato);
			ai.setDataCreazione(new Date());
			entityManager.persist(ai);
		}
		entityManager.detach(ai);
		return ai;
	}

	public void creaDatiGenerali(SchedaCandidato scheda) {
		DatiGenerali dg = new DatiGenerali();
		dg.setSchedaCandidato(scheda);
		dg.setDataCreazione(new Date());
	}
	
	public Users caricaCredenziali(SchedaCandidato scheda) {
		String hql = "select a from "+Users.class.getName() +" as a where a.userId=?";
		Users user = (Users) entityManager.createQuery(hql).setParameter(1, scheda.getIdSchedaCandidato()).getSingleResult();
		entityManager.detach(user);
		return user;
	}
	
	public Boolean checkNomeDocumento( String nome,Long idCandidato) {
		String nativeSql = "select count(*) from cv_candidato as a where a.id_candidato = ? and a.nome = ?";				
		Query query = entityManager.createNativeQuery(nativeSql);
		query.setParameter(1, idCandidato);
		query.setParameter(2, nome);
		
		BigInteger result = (BigInteger)query.getSingleResult();
		if (result.intValue()>0){
			
	     	return false;
		
		}
		return true;
		
	}
	
	public CVCandidato caricaUltimoDocumento( Long idCandidato, String tipo) {
		String nativeSql = "select a.* from cv_candidato as a where a.id_candidato = ? and a.tipo = ? and a.id_documento = " +
				"(Select max(id_documento) from cv_candidato where id_candidato = ? and tipo = ?)";
		Query query = entityManager.createNativeQuery(nativeSql);
		query.setParameter(1, idCandidato);
		query.setParameter(2, tipo);
		query.setParameter(3, idCandidato);
		query.setParameter(4, tipo);
		
		List<Object[]> result = query.getResultList();
		if (result.size()>0){
			Object[] record = result.get(0);
		    CVCandidato doc = new CVCandidato();
	     	doc.setTitolo((String)record[4]);
	     	doc.setNome((String)record[5]);
	     	entityManager.detach(result);
		
	     	return doc;
		
		}
		return null;
		
	}
	
	public List<CVCandidato> caricaDocumentoConNome( Long idCandidato, String nome,String ext) {
		String hql = "select a from "+CVCandidato.class.getName() +" as a where a.idCandidato=? and a.estensione = ? and a.nome like '"+nome+"%'";
		List<CVCandidato> listDoc = entityManager.createQuery(hql).setParameter(1, idCandidato).setParameter(2, ext).getResultList();
		entityManager.detach(listDoc);
		return listDoc;
		
	}
	
	public NoteSelezionatore caricaNote(SchedaCandidato schedaCandidato) {
		String hql ="select s from "+NoteSelezionatore.class.getName()+" as s inner join fetch s.schedaCandidato sc where s.schedaCandidato=?";
		NoteSelezionatore ns = new NoteSelezionatore();
		try{
			ns = (NoteSelezionatore) entityManager.createQuery(hql).setParameter(1, schedaCandidato).getSingleResult();
			entityManager.detach(ns);
		}catch (NoResultException ne){
						
		}
		return ns;
	}
	
}